<?php

namespace app\admin\model\scanwork;

use think\Model;

/**
 * 产品溯源模型
 */
class Traceability extends Model
{
    // 表名
    protected $name = 'scanwork_traceability';
    
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    
    // 追加属性
    protected $append = [
        'status_text'
    ];
    
    // 溯源状态
    public function getStatusList()
    {
        return [
            '0' => __('异常'),
            '1' => __('正常')
        ];
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    // 关联订单
    public function order()
    {
        return $this->belongsTo('app\admin\model\scanwork\Order', 'order_id', 'id');
    }

    // 关联产品
    public function product()
    {
        return $this->belongsTo('app\admin\model\scanwork\Product', 'product_id', 'id');
    }

    // 关联型号
    public function model()
    {
        return $this->belongsTo('app\admin\model\scanwork\ProductModel', 'model_id', 'id');
    }

    // 关联客户
    public function customer()
    {
        return $this->belongsTo('app\admin\model\scanwork\Customer', 'customer_id', 'id');
    }

    // 关联生产计划
    public function productionPlan()
    {
        return $this->belongsTo('app\admin\model\scanwork\ProductionPlan', 'production_plan_id', 'id');
    }

    // 获取溯源码
    public function getTraceCodeAttr($value, $data)
    {
        if (empty($value) && isset($data['id'])) {
            $value = 'SY-' . date('Y') . '-' . str_pad($data['id'], 3, '0', STR_PAD_LEFT);
        }
        return $value;
    }

    // 检查溯源码是否唯一
    public function checkCodeUnique($code, $id = null)
    {
        $where = ['trace_code' => $code];
        if ($id) {
            $where['id'] = ['<>', $id];
        }
        return $this->where($where)->count() == 0;
    }

    // 获取生产过程记录
    public function getProductionProcessAttr($value, $data)
    {
        if (is_string($value)) {
            return json_decode($value, true) ?: [];
        }
        return $value ?: [];
    }

    // 设置生产过程记录
    public function setProductionProcessAttr($value, $data)
    {
        if (is_array($value)) {
            return json_encode($value, JSON_UNESCAPED_UNICODE);
        }
        return $value;
    }

    // 获取质量记录
    public function getQualityRecordsAttr($value, $data)
    {
        if (is_string($value)) {
            return json_decode($value, true) ?: [];
        }
        return $value ?: [];
    }

    // 设置质量记录
    public function setQualityRecordsAttr($value, $data)
    {
        if (is_array($value)) {
            return json_encode($value, JSON_UNESCAPED_UNICODE);
        }
        return $value;
    }

    // 获取员工记录
    public function getEmployeeRecordsAttr($value, $data)
    {
        if (is_string($value)) {
            return json_decode($value, true) ?: [];
        }
        return $value ?: [];
    }

    // 设置员工记录
    public function setEmployeeRecordsAttr($value, $data)
    {
        if (is_array($value)) {
            return json_encode($value, JSON_UNESCAPED_UNICODE);
        }
        return $value;
    }

    // 获取设备记录
    public function getEquipmentRecordsAttr($value, $data)
    {
        if (is_string($value)) {
            return json_decode($value, true) ?: [];
        }
        return $value ?: [];
    }

    // 设置设备记录
    public function setEquipmentRecordsAttr($value, $data)
    {
        if (is_array($value)) {
            return json_encode($value, JSON_UNESCAPED_UNICODE);
        }
        return $value;
    }

    // 获取物料记录
    public function getMaterialRecordsAttr($value, $data)
    {
        if (is_string($value)) {
            return json_decode($value, true) ?: [];
        }
        return $value ?: [];
    }

    // 设置物料记录
    public function setMaterialRecordsAttr($value, $data)
    {
        if (is_array($value)) {
            return json_encode($value, JSON_UNESCAPED_UNICODE);
        }
        return $value;
    }

    // 生成溯源码
    private function generateTraceCode()
    {
        $prefix = 'SY-' . date('Y') . '-';
        $lastCode = $this->where('trace_code', 'like', $prefix . '%')
            ->order('trace_code desc')
            ->value('trace_code');
        
        if ($lastCode) {
            $lastNumber = intval(substr($lastCode, -3));
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }
        
        return $prefix . str_pad($newNumber, 3, '0', STR_PAD_LEFT);
    }

    // 创建产品溯源记录
    public function createTraceability($orderId, $productId, $modelId, $customerId, $productionPlanId = null)
    {
        $order = \app\admin\model\scanwork\Order::get($orderId);
        if (!$order) {
            throw new \Exception('订单不存在');
        }

        $product = \app\admin\model\scanwork\Product::get($productId);
        if (!$product) {
            throw new \Exception('产品不存在');
        }

        $model = \app\admin\model\scanwork\ProductModel::get($modelId);
        if (!$model) {
            throw new \Exception('产品型号不存在');
        }

        $customer = \app\admin\model\scanwork\Customer::get($customerId);
        if (!$customer) {
            throw new \Exception('客户不存在');
        }

        // 检查是否已存在溯源记录
        $existing = $this->where([
            'order_id' => $orderId,
            'product_id' => $productId,
            'model_id' => $modelId
        ])->find();

        if ($existing) {
            throw new \Exception('该产品的溯源记录已存在');
        }

        // 收集生产过程数据
        $productionProcess = $this->collectProductionProcess($orderId, $modelId);
        $qualityRecords = $this->collectQualityRecords($orderId, $modelId);
        $employeeRecords = $this->collectEmployeeRecords($orderId, $modelId);
        $equipmentRecords = $this->collectEquipmentRecords($orderId, $modelId);
        $materialRecords = $this->collectMaterialRecords($orderId, $modelId);

        // 创建溯源记录
        $data = [
            'trace_code' => $this->generateTraceCode(),
            'order_id' => $orderId,
            'product_id' => $productId,
            'model_id' => $modelId,
            'production_plan_id' => $productionPlanId,
            'customer_id' => $customerId,
            'production_start_time' => $productionProcess['start_time'] ?? null,
            'production_end_time' => $productionProcess['end_time'] ?? null,
            'production_process' => $productionProcess,
            'quality_records' => $qualityRecords,
            'employee_records' => $employeeRecords,
            'equipment_records' => $equipmentRecords,
            'material_records' => $materialRecords,
            'status' => 1,
            'createtime' => time()
        ];

        return $this->create($data);
    }

    // 收集生产过程数据
    private function collectProductionProcess($orderId, $modelId)
    {
        $allocations = \app\admin\model\scanwork\Allocation::with(['process', 'reports'])
            ->where('order_id', $orderId)
            ->where('model_id', $modelId)
            ->select();

        $processData = [];
        $startTime = null;
        $endTime = null;

        foreach ($allocations as $allocation) {
            $processInfo = [
                'process_id' => $allocation->process_id,
                'process_name' => $allocation->process->name,
                'allocated_quantity' => $allocation->quantity,
                'reported_quantity' => $allocation->reported_quantity,
                'start_time' => $allocation->actual_start_time,
                'end_time' => $allocation->actual_end_time,
                'actual_hours' => $allocation->actual_hours,
                'reports' => []
            ];

            // 收集报工记录
            foreach ($allocation->reports as $report) {
                if ($report->status == 1) { // 只统计已确认的报工
                    $processInfo['reports'][] = [
                        'report_id' => $report->id,
                        'quantity' => $report->quantity,
                        'actual_hours' => $report->actual_hours,
                        'quality_status' => $report->quality_status,
                        'report_time' => $report->createtime,
                        'production_images' => $report->production_images
                    ];

                    if (!$startTime || $report->createtime < $startTime) {
                        $startTime = $report->createtime;
                    }
                    if (!$endTime || $report->createtime > $endTime) {
                        $endTime = $report->createtime;
                    }
                }
            }

            $processData[] = $processInfo;
        }

        return [
            'start_time' => $startTime,
            'end_time' => $endTime,
            'processes' => $processData
        ];
    }

    // 收集质量记录
    private function collectQualityRecords($orderId, $modelId)
    {
        $reports = \app\admin\model\scanwork\Report::with(['allocation.process'])
            ->where('allocation_id', 'in', function($query) use ($orderId, $modelId) {
                $query->table('fa_scanwork_allocation')
                    ->where('order_id', $orderId)
                    ->where('model_id', $modelId)
                    ->field('id');
            })
            ->where('status', 1)
            ->select();

        $qualityData = [];
        foreach ($reports as $report) {
            $qualityData[] = [
                'report_id' => $report->id,
                'process_name' => $report->allocation->process->name,
                'quantity' => $report->quantity,
                'quality_status' => $report->quality_status,
                'audit_images' => $report->audit_images,
                'audit_videos' => $report->audit_videos,
                'audit_notes' => $report->audit_notes,
                'audit_time' => $report->audit_time,
                'auditor_id' => $report->auditor_id
            ];
        }

        return $qualityData;
    }

    // 收集员工记录
    private function collectEmployeeRecords($orderId, $modelId)
    {
        $allocations = \app\admin\model\scanwork\Allocation::with(['user', 'process', 'reports'])
            ->where('order_id', $orderId)
            ->where('model_id', $modelId)
            ->select();

        $employeeData = [];
        foreach ($allocations as $allocation) {
            $totalQuantity = $allocation->reports->where('status', 1)->sum('quantity');
            $totalHours = $allocation->reports->where('status', 1)->sum('actual_hours');

            $employeeData[] = [
                'user_id' => $allocation->user_id,
                'user_name' => $allocation->user->nickname,
                'process_name' => $allocation->process->name,
                'allocated_quantity' => $allocation->quantity,
                'completed_quantity' => $totalQuantity,
                'total_hours' => $totalHours,
                'allocation_time' => $allocation->createtime,
                'completion_time' => $allocation->reports->where('status', 1)->max('createtime')
            ];
        }

        return $employeeData;
    }

    // 收集设备记录
    private function collectEquipmentRecords($orderId, $modelId)
    {
        // 这里可以根据实际需求收集设备使用记录
        // 目前返回空数组，后续可以扩展
        return [];
    }

    // 收集物料记录
    private function collectMaterialRecords($orderId, $modelId)
    {
        // 这里可以根据实际需求收集物料使用记录
        // 目前返回空数组，后续可以扩展
        return [];
    }

    // 更新溯源记录
    public function updateTraceability()
    {
        if (!$this->order_id || !$this->model_id) {
            throw new \Exception('溯源记录数据不完整');
        }

        // 重新收集数据
        $productionProcess = $this->collectProductionProcess($this->order_id, $this->model_id);
        $qualityRecords = $this->collectQualityRecords($this->order_id, $this->model_id);
        $employeeRecords = $this->collectEmployeeRecords($this->order_id, $this->model_id);
        $equipmentRecords = $this->collectEquipmentRecords($this->order_id, $this->model_id);
        $materialRecords = $this->collectMaterialRecords($this->order_id, $this->model_id);

        // 更新记录
        $this->save([
            'production_start_time' => $productionProcess['start_time'],
            'production_end_time' => $productionProcess['end_time'],
            'production_process' => $productionProcess,
            'quality_records' => $qualityRecords,
            'employee_records' => $employeeRecords,
            'equipment_records' => $equipmentRecords,
            'material_records' => $materialRecords,
            'updatetime' => time()
        ]);
    }

    // 获取溯源摘要信息（用于扫码显示）
    public function getTraceSummary()
    {
        $order = $this->order;
        $product = $this->product;
        $model = $this->model;
        $customer = $this->customer;

        $productionProcess = $this->production_process;
        $qualityRecords = $this->quality_records;
        $employeeRecords = $this->employee_records;

        // 计算质量合格率
        $totalQuantity = 0;
        $qualifiedQuantity = 0;
        foreach ($qualityRecords as $record) {
            $totalQuantity += $record['quantity'];
            if ($record['quality_status'] == 1) {
                $qualifiedQuantity += $record['quantity'];
            }
        }
        $qualityRate = $totalQuantity > 0 ? round($qualifiedQuantity / $totalQuantity * 100, 2) : 0;

        // 统计参与员工
        $employees = [];
        foreach ($employeeRecords as $record) {
            if (!isset($employees[$record['user_id']])) {
                $employees[$record['user_id']] = [
                    'user_name' => $record['user_name'],
                    'processes' => []
                ];
            }
            $employees[$record['user_id']]['processes'][] = $record['process_name'];
        }

        return [
            'trace_code' => $this->trace_code,
            'order_no' => $order->order_no,
            'customer_name' => $customer->customer_name,
            'product_name' => $product->name,
            'model_name' => $model->name,
            'production_start_time' => $this->production_start_time ? date('Y-m-d H:i:s', $this->production_start_time) : '',
            'production_end_time' => $this->production_end_time ? date('Y-m-d H:i:s', $this->production_end_time) : '',
            'total_quantity' => $totalQuantity,
            'qualified_quantity' => $qualifiedQuantity,
            'quality_rate' => $qualityRate,
            'process_count' => count($productionProcess['processes']),
            'employee_count' => count($employees),
            'employees' => $employees,
            'status' => $this->status_text
        ];
    }

    // 获取详细溯源信息
    public function getTraceDetails()
    {
        $summary = $this->getTraceSummary();
        
        return array_merge($summary, [
            'production_process' => $this->production_process,
            'quality_records' => $this->quality_records,
            'employee_records' => $this->employee_records,
            'equipment_records' => $this->equipment_records,
            'material_records' => $this->material_records
        ]);
    }

    // 批量创建溯源记录
    public function batchCreateTraceabilities($orderId)
    {
        $order = \app\admin\model\scanwork\Order::get($orderId);
        if (!$order) {
            throw new \Exception('订单不存在');
        }

        $orderModels = \app\admin\model\scanwork\OrderModel::with(['model.product'])
            ->where('order_id', $orderId)
            ->select();

        $results = [];
        $successCount = 0;
        $errorCount = 0;
        $errors = [];

        foreach ($orderModels as $orderModel) {
            try {
                $traceability = $this->createTraceability(
                    $orderId,
                    $orderModel->model->product_id,
                    $orderModel->model_id,
                    $order->customer_id
                );
                $results[] = $traceability;
                $successCount++;
            } catch (\Exception $e) {
                $errorCount++;
                $errors[] = "产品【{$orderModel->model->product->name} - {$orderModel->model->name}】: " . $e->getMessage();
            }
        }

        return [
            'success_count' => $successCount,
            'error_count' => $errorCount,
            'errors' => $errors,
            'results' => $results
        ];
    }
}
